package com.xiaotao.util;

import com.xiaotao.entity.Merchant;
import com.xiaotao.mapper.MerchantMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.domain.geo.GeoLocation;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class RedisGeoUtil {

    @Resource
    private RedisTemplate<String, Object> redisTemplateInit;
    @Resource
    private MerchantMapper merchantMapper;

    // GEO 集合的 key（统一管理，方便维护）
    private static final String MERCHANT_GEO_KEY = "merchants:geo";

    /**
     * 添加商户位置到 GEO 集合
     * @param merchant 商户信息（需包含 id、longitude、latitude）
     */
    public void addMerchantLocation(Merchant merchant) {
        redisTemplateInit.opsForGeo().add(
                MERCHANT_GEO_KEY,
                new Point(merchant.getLongitude().doubleValue(), merchant.getLatitude().doubleValue()),
                merchant.getId()
        );
    }

    /**
     * 根据用户位置查询附近商户
     * @param userLon 用户经度
     * @param userLat 用户纬度
     * @param radius  查询半径（单位：公里）
     * @param limit   最多返回数量
     * @return 商户ID + 距离的列表（按距离升序）
     */
    public GeoResults<RedisGeoCommands.GeoLocation<Object>> searchNearbyMerchants(
            Double userLon, Double userLat, Double radius, Long limit) {

        // 定义查询条件：以用户位置为中心，radius 公里范围内
        Circle circle = new Circle(new Point(userLon, userLat), new Distance(radius, Metrics.KILOMETERS));

        // 定义查询参数：按距离升序，限制返回数量
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs
                .newGeoRadiusArgs()
                .includeDistance()
                .sortAscending()
                .limit(limit);
        //判断redis中是否有MERCHANT_GEO_KEY，如果没有说明没有商户或者redis出问题了，此时先查询数据库，将数据库数据插入
        Boolean flag = redisTemplateInit.hasKey(MERCHANT_GEO_KEY);
        if (!flag){
            //不存在，查数据库
            List<Merchant> all = merchantMapper.findAll();
            if (all==null){
                //说明数据库也没数据，此时直接返回null
                return null;
            }
            //数据库有数据，插入redis
            batchAddMerchants(all);
        }
        //返回数据
        return redisTemplateInit.opsForGeo().radius(MERCHANT_GEO_KEY, circle, args);
    }

    /**
     * 删除商户位置（GEO 底层是 ZSet，用 ZREM 命令）
     * @param merchantId 商户ID
     */
    public void removeMerchantLocation(Integer merchantId) {
        redisTemplateInit.opsForZSet().remove(MERCHANT_GEO_KEY, merchantId);
    }

    /**
     * 获取商户的经纬度
     * @param merchantId 商户ID
     * @return 经纬度点（null 表示不存在）
     */
    public Point getMerchantPoint(Integer merchantId) {
        List<Point> points = redisTemplateInit.opsForGeo().position(MERCHANT_GEO_KEY, merchantId);
        return points.isEmpty() ? null : points.get(0);
    }

    /**
     * 批量添加商家位置 - 方式2：使用商家列表
     */
    public void batchAddMerchants(List<Merchant> merchants) {
        if (merchants == null || merchants.isEmpty()) {
            log.warn("批量添加商家位置：商家列表为空");
            return;
        }

        try {
            Map<Object, Point> locations = new HashMap<>();
            for (Merchant merchant : merchants) {
                if (isValidMerchantLocation(merchant)) {
                    locations.put(
                            merchant.getId(),
                            new Point(merchant.getLongitude().doubleValue(), merchant.getLatitude().doubleValue())
                    );
                }
            }

            if (!locations.isEmpty()) {
                redisTemplateInit.opsForGeo().add(MERCHANT_GEO_KEY, locations);
                log.info("批量添加商家位置成功，有效数量：{}，总数：{}", locations.size(), merchants.size());
            } else {
                log.warn("没有有效的商家位置数据");
            }

        } catch (Exception e) {
            log.error("批量添加商家位置失败", e);
            throw new RuntimeException("批量添加商家位置失败", e);
        }
    }



    /**
     * 验证商家位置数据
     */
    private boolean isValidMerchantLocation(Merchant merchant) {
        if (merchant == null) {
            return false;
        }

        if (merchant.getId() == null) {
            log.warn("商家ID为空，跳过");
            return false;
        }

        if (merchant.getLongitude() == null || merchant.getLatitude() == null) {
            log.warn("商家 {} 经纬度为空，跳过", merchant.getId());
            return false;
        }

        // 验证经纬度范围（中国大致范围）
        double lng = merchant.getLongitude().doubleValue();
        double lat = merchant.getLatitude().doubleValue();

        if (lng < 73.66 || lng > 135.05 || lat < 3.86 || lat > 53.55) {
            log.warn("商家 {} 经纬度超出有效范围: {}, {}", merchant.getId(), lng, lat);
            return false;
        }

        return true;
    }
}
